/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entidade.controller.JPA;

import entidade.controller.JPA.exceptions.IllegalOrphanException;
import entidade.controller.JPA.exceptions.NonexistentEntityException;
import entidade.controller.JPA.exceptions.RollbackFailureException;
import entidade.persistencia.Venda;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import entidade.persistencia.Funcionario;
import entidade.persistencia.Usuario;
import entidade.persistencia.EntradaSaida;
import entidade.persistencia.OpercaoExtra;
import java.util.ArrayList;
import java.util.List;
import entidade.persistencia.ProdutoVenda;
import entidade.persistencia.ProdutoVendaPK;
import javax.faces.context.FacesContext;
import javax.transaction.UserTransaction;

/**
 *
 * @author victorinox
 */
public class VendaJpaController {

    @Resource
    private UserTransaction utx = null;
    @PersistenceUnit(unitName = "globalimage2PU")
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Venda venda) throws RollbackFailureException, Exception {
        if (venda.getEntradaSaidaCollection() == null) {
            venda.setEntradaSaidaCollection(new ArrayList<EntradaSaida>());
        }
        if (venda.getProdutoVendaCollection() == null) {
            venda.setProdutoVendaCollection(new ArrayList<ProdutoVenda>());
        }
         if (venda.getOpercaoExtraCollection() == null) {
            venda.setOpercaoExtraCollection(new ArrayList<OpercaoExtra>());
        }
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Funcionario funcionarioId = venda.getFuncionarioId();
            if (funcionarioId != null) {
                funcionarioId = em.getReference(funcionarioId.getClass(), funcionarioId.getFuncionarioId());
                venda.setFuncionarioId(funcionarioId);
            }
            Usuario clienteId = venda.getClienteId();
            if (clienteId != null) {
                clienteId = em.getReference(clienteId.getClass(), clienteId.getUsuarioId());
                venda.setClienteId(clienteId);
            }
            Usuario transportadorId = venda.getTransportadorId();
            if (transportadorId != null) {
                transportadorId = em.getReference(transportadorId.getClass(), transportadorId.getUsuarioId());
                venda.setTransportadorId(transportadorId);
            }
            List<EntradaSaida> attachedEntradaSaidaCollection = new ArrayList<EntradaSaida>();
            for (EntradaSaida entradaSaidaCollectionEntradaSaidaToAttach : venda.getEntradaSaidaCollection()) {
                entradaSaidaCollectionEntradaSaidaToAttach = em.getReference(entradaSaidaCollectionEntradaSaidaToAttach.getClass(), entradaSaidaCollectionEntradaSaidaToAttach.getEntradaSaidaId());
                attachedEntradaSaidaCollection.add(entradaSaidaCollectionEntradaSaidaToAttach);
            }
            venda.setEntradaSaidaCollection(attachedEntradaSaidaCollection);
            List<OpercaoExtra> attachedOpercaoExtraCollection = new ArrayList<OpercaoExtra>();
            for (OpercaoExtra opercaoExtraCollectionOpercaoExtraToAttach : venda.getOpercaoExtraCollection()) {
                opercaoExtraCollectionOpercaoExtraToAttach = em.getReference(opercaoExtraCollectionOpercaoExtraToAttach.getClass(), opercaoExtraCollectionOpercaoExtraToAttach.getOperacaoExtraId());
                attachedOpercaoExtraCollection.add(opercaoExtraCollectionOpercaoExtraToAttach);
            }
            venda.setOpercaoExtraCollection(attachedOpercaoExtraCollection);
            List<ProdutoVenda> attachedProdutoVendaCollection = new ArrayList<ProdutoVenda>();
            for (ProdutoVenda produtoVendaCollectionProdutoVendaToAttach : venda.getProdutoVendaCollection()) {
                produtoVendaCollectionProdutoVendaToAttach = em.getReference(produtoVendaCollectionProdutoVendaToAttach.getClass(), produtoVendaCollectionProdutoVendaToAttach.getProdutoVendaPK());
                attachedProdutoVendaCollection.add(produtoVendaCollectionProdutoVendaToAttach);
            }
            venda.setProdutoVendaCollection(attachedProdutoVendaCollection);
            em.persist(venda);
            if (funcionarioId != null) {
                funcionarioId.getVendaCollection().add(venda);
                funcionarioId = em.merge(funcionarioId);
            }
            if (clienteId != null) {
                clienteId.getVendaCollection().add(venda);
                clienteId = em.merge(clienteId);
            }
            if (transportadorId != null) {
                transportadorId.getVendaCollection().add(venda);
                transportadorId = em.merge(transportadorId);
            }
            for (EntradaSaida entradaSaidaCollectionEntradaSaida : venda.getEntradaSaidaCollection()) {
                entradaSaidaCollectionEntradaSaida.getVendaCollection().add(venda);
                entradaSaidaCollectionEntradaSaida = em.merge(entradaSaidaCollectionEntradaSaida);
            }
            for (OpercaoExtra opercaoExtraCollectionOpercaoExtra : venda.getOpercaoExtraCollection()) {
                Venda oldVendaIdOfOpercaoExtraCollectionOpercaoExtra = opercaoExtraCollectionOpercaoExtra.getVendaId();
                opercaoExtraCollectionOpercaoExtra.setVendaId(venda);
                opercaoExtraCollectionOpercaoExtra = em.merge(opercaoExtraCollectionOpercaoExtra);
                if (oldVendaIdOfOpercaoExtraCollectionOpercaoExtra != null) {
                    oldVendaIdOfOpercaoExtraCollectionOpercaoExtra.getOpercaoExtraCollection().remove(opercaoExtraCollectionOpercaoExtra);
                    oldVendaIdOfOpercaoExtraCollectionOpercaoExtra = em.merge(oldVendaIdOfOpercaoExtraCollectionOpercaoExtra);
                }
            }
            for (ProdutoVenda produtoVendaCollectionProdutoVenda : venda.getProdutoVendaCollection()) {
                Venda oldVendaOfProdutoVendaCollectionProdutoVenda = produtoVendaCollectionProdutoVenda.getVenda();
                produtoVendaCollectionProdutoVenda.setVenda(venda);
                produtoVendaCollectionProdutoVenda = em.merge(produtoVendaCollectionProdutoVenda);
                if (oldVendaOfProdutoVendaCollectionProdutoVenda != null) {
                    oldVendaOfProdutoVendaCollectionProdutoVenda.getProdutoVendaCollection().remove(produtoVendaCollectionProdutoVenda);
                    oldVendaOfProdutoVendaCollectionProdutoVenda = em.merge(oldVendaOfProdutoVendaCollectionProdutoVenda);
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Venda venda) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Venda persistentVenda = em.find(Venda.class, venda.getVendaId());
            Funcionario funcionarioIdOld = persistentVenda.getFuncionarioId();
            Funcionario funcionarioIdNew = venda.getFuncionarioId();
            Usuario clienteIdOld = persistentVenda.getClienteId();
            Usuario clienteIdNew = venda.getClienteId();
            Usuario transportadorIdOld = persistentVenda.getTransportadorId();
            Usuario transportadorIdNew = venda.getTransportadorId();
            List<EntradaSaida> entradaSaidaCollectionOld = persistentVenda.getEntradaSaidaCollection();
            List<EntradaSaida> entradaSaidaCollectionNew = venda.getEntradaSaidaCollection();
            List<OpercaoExtra> opercaoExtraCollectionOld = persistentVenda.getOpercaoExtraCollection();
            List<OpercaoExtra> opercaoExtraCollectionNew = venda.getOpercaoExtraCollection();
            List<ProdutoVenda> produtoVendaCollectionOld = persistentVenda.getProdutoVendaCollection();
            List<ProdutoVenda> produtoVendaCollectionNew = venda.getProdutoVendaCollection();
            List<String> illegalOrphanMessages = null;
            for (ProdutoVenda produtoVendaCollectionOldProdutoVenda : produtoVendaCollectionOld) {
                if (!produtoVendaCollectionNew.contains(produtoVendaCollectionOldProdutoVenda)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain ProdutoVenda " + produtoVendaCollectionOldProdutoVenda + " since its venda field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (funcionarioIdNew != null) {
                funcionarioIdNew = em.getReference(funcionarioIdNew.getClass(), funcionarioIdNew.getFuncionarioId());
                venda.setFuncionarioId(funcionarioIdNew);
            }
            if (clienteIdNew != null) {
                clienteIdNew = em.getReference(clienteIdNew.getClass(), clienteIdNew.getUsuarioId());
                venda.setClienteId(clienteIdNew);
            }
            if (transportadorIdNew != null) {
                transportadorIdNew = em.getReference(transportadorIdNew.getClass(), transportadorIdNew.getUsuarioId());
                venda.setTransportadorId(transportadorIdNew);
            }
            List<EntradaSaida> attachedEntradaSaidaCollectionNew = new ArrayList<EntradaSaida>();
            for (EntradaSaida entradaSaidaCollectionNewEntradaSaidaToAttach : entradaSaidaCollectionNew) {
                entradaSaidaCollectionNewEntradaSaidaToAttach = em.getReference(entradaSaidaCollectionNewEntradaSaidaToAttach.getClass(), entradaSaidaCollectionNewEntradaSaidaToAttach.getEntradaSaidaId());
                attachedEntradaSaidaCollectionNew.add(entradaSaidaCollectionNewEntradaSaidaToAttach);
            }
            entradaSaidaCollectionNew = attachedEntradaSaidaCollectionNew;
            venda.setEntradaSaidaCollection(entradaSaidaCollectionNew);
            List<OpercaoExtra> attachedOpercaoExtraCollectionNew = new ArrayList<OpercaoExtra>();
            for (OpercaoExtra opercaoExtraCollectionNewOpercaoExtraToAttach : opercaoExtraCollectionNew) {
                opercaoExtraCollectionNewOpercaoExtraToAttach = em.getReference(opercaoExtraCollectionNewOpercaoExtraToAttach.getClass(), opercaoExtraCollectionNewOpercaoExtraToAttach.getOperacaoExtraId());
                attachedOpercaoExtraCollectionNew.add(opercaoExtraCollectionNewOpercaoExtraToAttach);
            }
            opercaoExtraCollectionNew = attachedOpercaoExtraCollectionNew;
            venda.setOpercaoExtraCollection(opercaoExtraCollectionNew);
            List<ProdutoVenda> attachedProdutoVendaCollectionNew = new ArrayList<ProdutoVenda>();

            for (ProdutoVenda produtoVendaCollectionNewProdutoVendaToAttach : produtoVendaCollectionNew) {

                if (produtoVendaCollectionNewProdutoVendaToAttach.getProdutoVendaPK() != null) {
                    produtoVendaCollectionNewProdutoVendaToAttach = em.getReference(produtoVendaCollectionNewProdutoVendaToAttach.getClass(), produtoVendaCollectionNewProdutoVendaToAttach.getProdutoVendaPK());
                }
                produtoVendaCollectionNewProdutoVendaToAttach.setVenda(venda);
                attachedProdutoVendaCollectionNew.add(produtoVendaCollectionNewProdutoVendaToAttach);
            }
            produtoVendaCollectionNew = attachedProdutoVendaCollectionNew;
            venda.setProdutoVendaCollection(produtoVendaCollectionNew);

            venda = em.merge(venda);
            if (funcionarioIdOld != null && !funcionarioIdOld.equals(funcionarioIdNew)) {
                funcionarioIdOld.getVendaCollection().remove(venda);
                funcionarioIdOld = em.merge(funcionarioIdOld);
            }
            if (funcionarioIdNew != null && !funcionarioIdNew.equals(funcionarioIdOld)) {
                funcionarioIdNew.getVendaCollection().add(venda);
                funcionarioIdNew = em.merge(funcionarioIdNew);
            }
            if (clienteIdOld != null && !clienteIdOld.equals(clienteIdNew)) {
                clienteIdOld.getVendaCollection().remove(venda);
                clienteIdOld = em.merge(clienteIdOld);
            }
            if (clienteIdNew != null && !clienteIdNew.equals(clienteIdOld)) {
                clienteIdNew.getVendaCollection().add(venda);
                clienteIdNew = em.merge(clienteIdNew);
            }
            if (transportadorIdOld != null && !transportadorIdOld.equals(transportadorIdNew)) {
                transportadorIdOld.getVendaCollection().remove(venda);
                transportadorIdOld = em.merge(transportadorIdOld);
            }
            if (transportadorIdNew != null && !transportadorIdNew.equals(transportadorIdOld)) {
                transportadorIdNew.getVendaCollection().add(venda);
                transportadorIdNew = em.merge(transportadorIdNew);
            }
            for (EntradaSaida entradaSaidaCollectionOldEntradaSaida : entradaSaidaCollectionOld) {
                if (!entradaSaidaCollectionNew.contains(entradaSaidaCollectionOldEntradaSaida)) {
                    entradaSaidaCollectionOldEntradaSaida.getVendaCollection().remove(venda);
                    entradaSaidaCollectionOldEntradaSaida = em.merge(entradaSaidaCollectionOldEntradaSaida);
                }
            }
            for (EntradaSaida entradaSaidaCollectionNewEntradaSaida : entradaSaidaCollectionNew) {
                if (!entradaSaidaCollectionOld.contains(entradaSaidaCollectionNewEntradaSaida)) {
                    entradaSaidaCollectionNewEntradaSaida.getVendaCollection().add(venda);
                    entradaSaidaCollectionNewEntradaSaida = em.merge(entradaSaidaCollectionNewEntradaSaida);
                }
            }
            for (OpercaoExtra opercaoExtraCollectionOldOpercaoExtra : opercaoExtraCollectionOld) {
                if (!opercaoExtraCollectionNew.contains(opercaoExtraCollectionOldOpercaoExtra)) {
                    opercaoExtraCollectionOldOpercaoExtra.setVendaId(null);
                    opercaoExtraCollectionOldOpercaoExtra = em.merge(opercaoExtraCollectionOldOpercaoExtra);
                }
            }
            for (OpercaoExtra opercaoExtraCollectionNewOpercaoExtra : opercaoExtraCollectionNew) {
                if (!opercaoExtraCollectionOld.contains(opercaoExtraCollectionNewOpercaoExtra)) {
                    Venda oldVendaIdOfOpercaoExtraCollectionNewOpercaoExtra = opercaoExtraCollectionNewOpercaoExtra.getVendaId();
                    opercaoExtraCollectionNewOpercaoExtra.setVendaId(venda);
                    opercaoExtraCollectionNewOpercaoExtra = em.merge(opercaoExtraCollectionNewOpercaoExtra);
                    if (oldVendaIdOfOpercaoExtraCollectionNewOpercaoExtra != null && !oldVendaIdOfOpercaoExtraCollectionNewOpercaoExtra.equals(venda)) {
                        oldVendaIdOfOpercaoExtraCollectionNewOpercaoExtra.getOpercaoExtraCollection().remove(opercaoExtraCollectionNewOpercaoExtra);
                        oldVendaIdOfOpercaoExtraCollectionNewOpercaoExtra = em.merge(oldVendaIdOfOpercaoExtraCollectionNewOpercaoExtra);
                    }
                }
            }
            for (ProdutoVenda produtoVendaCollectionNewProdutoVenda : produtoVendaCollectionNew) {
                if (!produtoVendaCollectionOld.contains(produtoVendaCollectionNewProdutoVenda)) {
                    Venda oldVendaOfProdutoVendaCollectionNewProdutoVenda = produtoVendaCollectionNewProdutoVenda.getVenda();
                    produtoVendaCollectionNewProdutoVenda.setVenda(venda);
                    if (produtoVendaCollectionNewProdutoVenda.getProdutoVendaPK() == null) {

                        ProdutoVendaPK pvpk = new ProdutoVendaPK(venda.getVendaId(), produtoVendaCollectionNewProdutoVenda.getProduto().getProdutoId());
                        produtoVendaCollectionNewProdutoVenda.setProdutoVendaPK(pvpk);

                        FacesContext facesContext = FacesContext.getCurrentInstance();
                        ProdutoVendaJpaController pvc = (ProdutoVendaJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "produtoVendaJpa");
                        pvc.createNoTransaction(produtoVendaCollectionNewProdutoVenda);
                        venda.getProdutoVendaCollection().add(produtoVendaCollectionNewProdutoVenda);

                    } else {
                        produtoVendaCollectionNewProdutoVenda = em.merge(produtoVendaCollectionNewProdutoVenda);
                        if (oldVendaOfProdutoVendaCollectionNewProdutoVenda != null && !oldVendaOfProdutoVendaCollectionNewProdutoVenda.equals(venda)) {
                            oldVendaOfProdutoVendaCollectionNewProdutoVenda.getProdutoVendaCollection().remove(produtoVendaCollectionNewProdutoVenda);
                            oldVendaOfProdutoVendaCollectionNewProdutoVenda = em.merge(oldVendaOfProdutoVendaCollectionNewProdutoVenda);
                        }
                    }
                }
            }
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction." + re, re);
            }
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = venda.getVendaId();
                if (findVenda(id) == null) {
                    throw new NonexistentEntityException("The venda with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Venda venda;
            try {
                venda = em.getReference(Venda.class, id);
                venda.getVendaId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The venda with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<ProdutoVenda> produtoVendaCollectionOrphanCheck = venda.getProdutoVendaCollection();
            for (ProdutoVenda produtoVendaCollectionOrphanCheckProdutoVenda : produtoVendaCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }

                FacesContext facesContext = FacesContext.getCurrentInstance();
                ProdutoVendaJpaController pvc = (ProdutoVendaJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "produtoVendaJpa");
                pvc.destroyNoTransaction(produtoVendaCollectionOrphanCheckProdutoVenda.getProdutoVendaPK());
            }

            Funcionario funcionarioId = venda.getFuncionarioId();
            if (funcionarioId != null) {
                funcionarioId.getVendaCollection().remove(venda);
                funcionarioId =
                        em.merge(funcionarioId);
            }

            Usuario clienteId = venda.getClienteId();
            if (clienteId != null) {
                clienteId.getVendaCollection().remove(venda);
                clienteId =
                        em.merge(clienteId);
            }

            Usuario transportadorId = venda.getTransportadorId();
            if (transportadorId != null) {
                transportadorId.getVendaCollection().remove(venda);
                transportadorId =
                        em.merge(transportadorId);
            }

            List<EntradaSaida> entradaSaidaCollection = venda.getEntradaSaidaCollection();
            for (EntradaSaida entradaSaidaCollectionEntradaSaida : entradaSaidaCollection) {
                entradaSaidaCollectionEntradaSaida.getVendaCollection().remove(venda);
                entradaSaidaCollectionEntradaSaida =
                        em.merge(entradaSaidaCollectionEntradaSaida);
            }
            List<OpercaoExtra> opercaoExtraCollection = venda.getOpercaoExtraCollection();
            for (OpercaoExtra opercaoExtraCollectionOpercaoExtra : opercaoExtraCollection) {
                opercaoExtraCollectionOpercaoExtra.setVendaId(null);
                opercaoExtraCollectionOpercaoExtra = em.merge(opercaoExtraCollectionOpercaoExtra);
            }

            em.remove(venda);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }

            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }

        }
    }

    public List<Venda> findVendaEntities() {
        return findVendaEntities(true, -1, -1);
    }

    public List<Venda> findVendaEntities(int maxResults, int firstResult) {
        return findVendaEntities(false, maxResults, firstResult);
    }

    private List<Venda> findVendaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Venda as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }

            return q.getResultList();
        } finally {
            em.close();
        }

    }

    public Venda findVenda(
            Integer id) {
        EntityManager em = getEntityManager();
        try {


            return em.find(Venda.class, id);
        } finally {
            em.close();
        }

    }

    public int getVendaCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Venda as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
}
